using System;
using System.Diagnostics;
using System.Threading;

namespace Eclipse.TRCore.Http
{
    public abstract class BaseAction<I, R> : IHttpAction<I, R> where I : new() where R : new()
    {
        private WebSession session;
        private ActionResult<R> actionResult = new ActionResult<R>();
        private HttpConfig httpConfig;
        private IAction nextAction;
        private IAction preAction;
        private Thread thread;
        protected volatile bool isAborted;
        private I input = new I();

        #region IHttpAction Members

        public I Input
        {
            get { return input; }
            set { input = value; }
        }

        public ActionResult<R> ActionResult
        {
            get { return actionResult; }
            set { actionResult = value; }
        }


        private int nestedlock = -1;

        public IAction NextAction
        {
            get { return nextAction; }
            set
            {
                Debug.Assert(value != this);
                nextAction = value;
                if (null != value && Interlocked.CompareExchange(ref nestedlock, 0, -1) == -1)
                {
                    value.PreAction = this;
                    Interlocked.CompareExchange(ref nestedlock, -1, 0);
                }
            }
        }

        public IAction PreAction
        {
            get { return preAction; }
            set
            {
                Debug.Assert(value != this);
                preAction = value;
                if (null != value && Interlocked.CompareExchange(ref nestedlock, 0, -1) == -1)
                {
                    value.NextAction = this;
                    Interlocked.CompareExchange(ref nestedlock, -1, 0);
                }
            }
        }

        WebSession IHttpAction.Session
        {
            get { return session; }
            set { session = value; }
        }


        HttpConfig IHttpAction.HttpConfig
        {
            get { return httpConfig; }
            set { httpConfig = value; }
        }

        void IAction.DoAction()
        {
            DoAction();
        }

        public abstract void DoAction();

        #endregion

        #region IExecutable Members

        
        public void Execute()
        {
            thread = Thread.CurrentThread;
            try
            {
                DoAction();
            }catch(Exception ex)
            {
                if (!(ex is ThreadAbortException))
                    throw;
                isAborted = true;
            }
        }

        public void Abort()
        {
            isAborted = true;
            Thread.SpinWait(200);
            if(null != thread && thread != Thread.CurrentThread && thread.IsAlive)
            {
                try
                {
                    thread.Abort();
                }catch{}
                thread = null;
            }
        }

        #endregion
    }

}
